﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommonClassLibrary
{
    internal class LogHelper
    {
        static LogHelper()
        {
            LogList = new ConcurrentQueue<LogHelper>();
            WriteLogFlag = false;
        }
        /// <summary>
        /// 操作时间
        /// </summary>
        public DateTime CreateTime { get; set; }
        /// <summary>
        /// 类型
        /// </summary>
        public string Type { get; set; }
        /// <summary>
        /// 标题
        /// </summary>
        public string Title { get; set; }
        /// <summary>
        /// 内容
        /// </summary>
        public string Content { get; set; }

        /// <summary>
        /// 全局待写入日志集合
        /// </summary>
        private static ConcurrentQueue<LogHelper> LogList { get; set; }
        /// <summary>
        /// 正在执行写入日志处理
        /// </summary>
        private static bool WriteLogFlag;

        public static void WriteLogRequest(string flag, string gysbh, string paramJson, enumOperateType operateType)
        {
            LogHelper log = new LogHelper();
            log.Title = operateType.ToString();
            log.Type = enumLogType.操作日志.ToString();
            log.Content = "标识:" + flag + ",供应商编号:" + gysbh + ",接收参数:" + paramJson;
            log.CreateTime = DateTime.Now;
            WritLog(log);
        }
        public static void WriteLog(string flag, enumOperateType operateType, string logInfo)
        {
            LogHelper log = new LogHelper();
            log.Title = operateType.ToString() + ",标识:" + flag;
            log.Content = logInfo;
            log.Type = enumLogType.操作日志.ToString();
            log.CreateTime = DateTime.Now;
            WritLog(log);
        }
        public static void WriteLog(string flag, enumOperateType operateType, string title, Exception ex)
        {
            LogHelper log = new LogHelper();
            log.Title = operateType.ToString() + ",标识:" + flag + ",异常描述:" + title;
            //log.Content = ex.Message + Environment.NewLine + GetExceptionLogContent(ex);
            log.Content = ex.ToString();
            log.Type = enumLogType.错误日志.ToString();
            log.CreateTime = DateTime.Now;
            WritLog(log);
        }
        private static void WritLog(LogHelper log, bool repeat = true)
        {
            LogList.Enqueue(log);
            if (WriteLogFlag)
                return;

            string tempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
            if (!Directory.Exists(tempPath))
                Directory.CreateDirectory(tempPath);
            WriteLogFlag = true;

            string lastFilePath = "";

            //FileStream fileStream = null;
            StreamWriter fileStream = null;
            try
            {
                while (LogList.Count > 0)
                {
                    LogHelper currentLog = null;
                    LogList.TryDequeue(out currentLog);
                    if (currentLog == null)
                    {
                        WriteLogFlag = false;
                        return;
                    }
                    tempPath = Path.Combine(tempPath, currentLog.CreateTime.ToString("yyyy-MM-dd") + ".txt");
                    if (!lastFilePath.Equals(tempPath))
                    {
                        if (fileStream != null)
                            fileStream.Dispose();
                        fileStream = File.AppendText(tempPath);
                        //fileStream = File.Open(tempPath,FileMode.OpenOrCreate,FileAccess.Write,FileShare.Read);// .AppendText(tempPath);
                        lastFilePath = tempPath;
                    }
                    else
                    {
                        if (fileStream == null)
                            //fileStream = File.Open(tempPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
                            fileStream = File.AppendText(tempPath);
                    }
                    try
                    {
                        string logContent = "时间:" + currentLog.CreateTime.ToString("yyyy-MM-dd HH:mm:ss:fff");
                        logContent += Environment.NewLine + "标题:" + currentLog.Title;
                        logContent += Environment.NewLine + "类型:" + currentLog.Type;
                        if (!string.IsNullOrEmpty(currentLog.Content))
                            logContent += Environment.NewLine + "内容:" + currentLog.Content;
                        logContent += Environment.NewLine;
                        byte[] byteContent = System.Text.Encoding.UTF8.GetBytes(logContent);


                        //fileStream.Seek(fileStream.Length,SeekOrigin.End);
                        //fileStream.Write(byteContent,0, byteContent.Length);
                        //fileStream.Flush();

                        fileStream.WriteLine(logContent);
                    }
                    catch (Exception ex)
                    {
                        LogHelper logModel = new LogHelper();
                        logModel.Title = ex.Message;
                        //logModel.Content = GetExceptionLogContent(ex);
                        logModel.Content = ex.ToString();
                        logModel.Type = enumLogType.异常日志.ToString();
                        logModel.CreateTime = DateTime.Now;
                        WriteErrorLog(logModel, currentLog, repeat);
                    }
                }
                fileStream.Flush();
            }
            catch (Exception outsideException)
            {
                LogHelper logModel = new LogHelper();
                logModel.Title = outsideException.Message;
                //logModel.Content = GetExceptionLogContent(outsideException);
                logModel.Content = outsideException.ToString();
                logModel.Type = enumLogType.异常日志.ToString();
                logModel.CreateTime = DateTime.Now;
                WriteErrorLog(logModel, null, repeat);
            }
            finally
            {
                fileStream.Dispose();
                WriteLogFlag = false;
            }
        }
        private static void WriteErrorLog(LogHelper log, LogHelper writeFailedLog, bool repeat = true)
        {
            string tempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "errorLogs");
            if (!Directory.Exists(tempPath))
                Directory.CreateDirectory(tempPath);
            tempPath = Path.Combine(tempPath, log.CreateTime.ToString("yyyy-MM-dd") + ".txt");
            try
            {
                using (StreamWriter sw = File.AppendText(tempPath))
                {
                    sw.WriteLine("时间:" + log.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"));
                    sw.WriteLine("标题:" + log.Title);
                    sw.WriteLine("类型:" + log.Type);
                    if (!string.IsNullOrEmpty(log.Content))
                        sw.WriteLine("内容:" + log.Content);
                    if (writeFailedLog != null)
                        sw.WriteLine("写入失败日志信息:" + writeFailedLog.ToJson());
                    sw.WriteLine("");
                    sw.Flush();
                }
            }
            catch (Exception ex)
            {
                if (repeat)
                {
                    LogHelper logModel = new LogHelper();
                    logModel.Title = ex.Message;
                    //logModel.Content = GetExceptionLogContent(ex);
                    logModel.Content = ex.ToString();
                    logModel.Type = enumLogType.异常日志.ToString();
                    logModel.CreateTime = DateTime.Now;
                    WritLog(logModel, false);
                }
            }
        }
        private static string GetExceptionLogContent(Exception ex)
        {
            if (ex == null)
                return "";
            string content = ex.StackTrace;
            while (ex.InnerException != null)
            {
                ex = ex.InnerException;
                content += Environment.NewLine + "内部错误信息:" + ex.Message + Environment.NewLine + ex.StackTrace;
            }
            return content;
        }
    }
    /// <summary>
    /// 日志类型
    /// </summary>
    public enum enumLogType
    {
        操作日志,
        错误日志,
        异常日志
    }
    /// <summary>
    /// 操作类型
    /// </summary>
    public enum enumOperateType
    {
        供应商编号获取订单,
        订单编号获取订单,
        供应商反馈订单,
        订单状态查询,
        反馈生产进度,
        装箱发货,
        供应商上传对账单,
        供应商上传对账单简易版,
        供应商上传文件,
        供应商取消文件,
        全局未处理异常
    }
}
